package com.mida.app.report.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.mida.app.report.service.MasterDataSvc;
import com.mida.app.report.service.RequestFormBmsSvc;
import com.mida.app.report.service.RequestFormUtilSvc;
import com.mida.app.report.vo.request.ExamsInfoVo;
import com.mida.app.report.vo.request.PatientPageInfoVo;
import com.mida.app.report.vo.request.RegistrationListCompleteInfoVo;
import com.mida.app.report.vo.request.SoidMapNameVo;
import com.mida.bms.customer.api.PersonOperationApi;
import com.mida.bms.customer.vo.person.PatientInfoVo;
import com.mida.bms.customer.vo.person.PersonInfoConditionVo;
import com.mida.bms.requestform.dto.RequestPageInfoDto;
import com.mida.bms.requestform.dto.ServiceInstanceInfoDto;
import com.mida.tool.common.ret.RespBody;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StopWatch;

import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CountDownLatch;
import java.util.stream.Collectors;

@Service
@Slf4j
public class RequestFormUtilSvcImpl implements RequestFormUtilSvc {
    /**
     * 主数据Api
     */
    @Autowired
    private MasterDataSvc masterDataSvc;

    @Autowired
    private PersonOperationApi personOperationApi;

    /**
     * 申请单域Api
     */
    @Autowired
    private RequestFormBmsSvc requestFormBmsSvc;


    /**
     * 批量查询检查服务实例名称
     */
    @Override
    public Map<BigDecimal, String> changeServiceInstanceNameSetMap(Set<BigDecimal> msdServiceInstanceSoids) {
        if (ObjectUtil.isEmpty(msdServiceInstanceSoids)) {
            return new ConcurrentHashMap<>();
        }
        return masterDataSvc.findServiceInstanceInfosBySoids(new ArrayList<BigDecimal>(msdServiceInstanceSoids));
    }

    /**
     * 批量查询业务单元名称
     */
    @Override
    public Map<BigDecimal, String> changeBusinessNameSetToMap(Set<BigDecimal> businessUnitSoids) {
        if (ObjectUtil.isEmpty(businessUnitSoids)) {
            return new ConcurrentHashMap<>();
        }
        return masterDataSvc.findBusinessUnitBySoids(new ArrayList<BigDecimal>(businessUnitSoids));
    }

    /**
     * 批量查询soid对应中文名
     */
    @Override
    public Map<BigDecimal, String> changeDataSetSoidNameSetToMap(Set<BigDecimal> dataSetSoids) {
        if (ObjectUtil.isEmpty(dataSetSoids)) {
            return new ConcurrentHashMap<>();
        }
        return masterDataSvc.findDataSetNamesBySoids(new ArrayList<BigDecimal>(dataSetSoids));
    }

    /**
     * 批量查询医生姓名
     */
    @Override
    public Map<BigDecimal, String> changeRequestDoctorSoidNameSetToMap(Set<BigDecimal> requestDoctorSoids) {
        if (ObjectUtil.isEmpty(requestDoctorSoids)) {
            return new ConcurrentHashMap<>();
        }
        return masterDataSvc.findRequestDoctorNameBySoids(new ArrayList<BigDecimal>(requestDoctorSoids));
    }


    /**
     * 获取需要批量查询的soid
     * 注意区分索引
     *
     * @param serviceInstanceMap
     * @return
     */
    @NotNull
    @Override
    public List<HashSet<BigDecimal>> changeSoidsMapToSets(Map<BigDecimal, List<ServiceInstanceInfoDto>> serviceInstanceMap) {
        HashSet<BigDecimal> msdServiceInstanceSoids = new HashSet<>();
        HashSet<BigDecimal> businessUnitSoids = new HashSet<>();
        HashSet<BigDecimal> dataSetSoids = new HashSet<>();
        HashSet<BigDecimal> requestDoctorSoids = new HashSet<>();
        List<BigDecimal> serviceInstanceMapKeyset = serviceInstanceMap.keySet().stream().filter(ObjectUtil::isNotEmpty).collect(Collectors.toList());
        for (BigDecimal serviceInstanceMapKey : serviceInstanceMapKeyset) {
            for (ServiceInstanceInfoDto serviceInstanceInfoDto : serviceInstanceMap.get(serviceInstanceMapKey)) {
                if (ObjectUtil.isEmpty(serviceInstanceInfoDto)) {
                    continue;
                }
                if (ObjectUtil.isNotEmpty(serviceInstanceInfoDto.getMsdServiceInstanceSoid())) {
                    msdServiceInstanceSoids.add(serviceInstanceInfoDto.getMsdServiceInstanceSoid());
                }
                if (ObjectUtil.isNotEmpty(serviceInstanceInfoDto.getExecuteDept())) {
                    businessUnitSoids.add(serviceInstanceInfoDto.getExecuteDept());
                }
                if (ObjectUtil.isNotEmpty(serviceInstanceInfoDto.getExamType())) {
                    dataSetSoids.add(serviceInstanceInfoDto.getExamType());
                }
                if (ObjectUtil.isNotEmpty(serviceInstanceInfoDto.getExamMethod())) {
                    dataSetSoids.add(serviceInstanceInfoDto.getExamMethod());
                }
                if (ObjectUtil.isNotEmpty(serviceInstanceInfoDto.getExamParts())) {
                    dataSetSoids.add(serviceInstanceInfoDto.getExamParts());
                }
                if (ObjectUtil.isNotEmpty(serviceInstanceInfoDto.getExamMethod())) {
                    dataSetSoids.add(serviceInstanceInfoDto.getExamMethod());
                }
                if (ObjectUtil.isNotEmpty(serviceInstanceInfoDto.getRequestDept())) {
                    businessUnitSoids.add(serviceInstanceInfoDto.getRequestDept());
                }
                if (ObjectUtil.isNotEmpty(serviceInstanceInfoDto.getRequestDoctor())) {
                    requestDoctorSoids.add(serviceInstanceInfoDto.getRequestDoctor());
                }
            }
        }
        return Arrays.asList(msdServiceInstanceSoids, businessUnitSoids, dataSetSoids, requestDoctorSoids);
    }

    /**
     * 分页数据多线程封装填充
     *
     * @param requestPageInfos         分页信息
     * @param records                  记录原有分页顺序的中间变量
     * @param personDetailInfosMap     患者信息map
     * @param serviceInstanceMap       检查服务实例信息map
     * @param serviceInstanceNameMap   检查服务实例属性名map
     * @param businessNameMap          业务单元名map(执行单元)
     * @param dataSetSoidNameMap       编码体系soid对应中文名map
     * @param requestDoctorSoidNameMap 员工姓名map
     */
    @Override
    public void extracted(List<RequestPageInfoDto> requestPageInfos,
                          Map<String, RegistrationListCompleteInfoVo> records,
                          Map<BigDecimal, PatientPageInfoVo> personDetailInfosMap,
                          Map<BigDecimal, List<ServiceInstanceInfoDto>> serviceInstanceMap,
                          Map<BigDecimal, String> serviceInstanceNameMap,
                          Map<BigDecimal, String> businessNameMap,
                          Map<BigDecimal, String> dataSetSoidNameMap,
                          Map<BigDecimal, String> requestDoctorSoidNameMap) {
//        ExecutorService executorService = Executors.newFixedThreadPool(4);
        try {
            final CountDownLatch latch = new CountDownLatch(requestPageInfos.size());
            for (RequestPageInfoDto requestPageInfo : requestPageInfos) {
//                executorService.execute(new Runnable() {
//                    @Override
//                    public void run() {
                try {
                    RegistrationListCompleteInfoVo registrationListCompleteInfoVo = RegistrationListCompleteInfoVo.builder()
                            //                                        .reqeustLifeCycleTimeType(getRequestLifeCycleTimeTypeName(requestPageInfo.getArlcRequestStatus()))
                            .requestSoid(ObjectUtils.isEmpty(requestPageInfo.getRequestSoid()) ? null : requestPageInfo.getRequestSoid())
                            .enconterSoid(ObjectUtils.isEmpty(requestPageInfo.getEnconterSoid()) ? null : requestPageInfo.getEnconterSoid())
                            .requestStatus(ObjectUtils.isEmpty(requestPageInfo.getRequestStatus()) ? null : requestPageInfo.getRequestStatus())
                            .requisitionId(ObjectUtils.isEmpty(requestPageInfo.getRequisitionId()) ? null : requestPageInfo.getRequisitionId())
                            .emergencySign(ObjectUtils.isEmpty(requestPageInfo.getEmergencySign()) ? null : requestPageInfo.getEmergencySign())
                            .manualSign(ObjectUtils.isEmpty(requestPageInfo.getManualSign()) ? null : requestPageInfo.getManualSign())
                            .clinicCardNo(requestPageInfo.getClinicCardNo())
                            //                                        .weight(requestPageInfo.getWeight())
                            .clinicCardType(ObjectUtils.isEmpty(requestPageInfo.getClinicCardType()) ? null : requestPageInfo.getClinicCardType())
                            .build();
                    if (null != requestPageInfo.getArlcCreateDate()) {
                        //放置当天申请单生命周期表中的最新操作时间，但是如果是预约时间，后面替换成预约检查的时间，而非操作预约的时间
                        registrationListCompleteInfoVo.setRequestLifeCycleTime(requestPageInfo.getArlcCreateDate());
                    }
                    if (null != requestPageInfo.getCreateDate()) {
                        registrationListCompleteInfoVo.setRequestTime(requestPageInfo.getCreateDate());
                    }
                    PatientPageInfoVo patientPageInfoVo = personDetailInfosMap.get(new BigDecimal(requestPageInfo.getCustomerSoid()));
                    registrationListCompleteInfoVo.setPatientPageInfoVo(patientPageInfoVo);
                    ExamsInfoVo examsInfoVo = ExamsInfoVo
                            .builder()
                            .doctorSoid(ObjectUtils.isEmpty(requestPageInfo.getRequestDoctor()) ? null : requestPageInfo.getRequestDoctor())
                            //从医生姓名map中获取开单医生姓名
                            .doctor(
                                    ObjectUtils.isEmpty(requestPageInfo.getRequestDoctor()) || ObjectUtils.isEmpty(requestDoctorSoidNameMap) ?
                                            null :
                                            requestDoctorSoidNameMap.get(new BigDecimal(requestPageInfo.getRequestDoctor()))
                            )
                            .businessUnitSoid(ObjectUtils.isEmpty(requestPageInfo.getRequestDept()) ? null : requestPageInfo.getRequestDept())
                            //从开单科室名称map中获取开单科室名
                            .businessUnitName(
                                    ObjectUtils.isEmpty(requestPageInfo.getRequestDept()) || ObjectUtil.isEmpty(businessNameMap) ?
                                            null :
                                            businessNameMap.get(new BigDecimal(requestPageInfo.getRequestDept()))
                            )
                            .build();
                    //封装检查项信息
                    dealExamInfo(serviceInstanceMap, requestPageInfo, examsInfoVo, businessNameMap, dataSetSoidNameMap, serviceInstanceNameMap);
                    //当前循环申请单下的所有检查服务实例
                    List<ServiceInstanceInfoDto> serviceInstanceInfoDtos = ObjectUtil.isEmpty(requestPageInfo.getRequestSoid()) ? null : serviceInstanceMap.get(new BigDecimal(requestPageInfo.getRequestSoid()));
                    if (ObjectUtils.isNotEmpty(serviceInstanceInfoDtos)) {
                        serviceInstanceInfoDtos.sort(new Comparator<ServiceInstanceInfoDto>() {
                            @Override
                            public int compare(ServiceInstanceInfoDto u1, ServiceInstanceInfoDto u2) {
                                return DateUtil.compare(u2.getBookingRegistDateTime(), u1.getBookingRegistDateTime());
                            }
                        });
                    }
                    registrationListCompleteInfoVo.setExamsInfoVo(examsInfoVo);
                    records.put(registrationListCompleteInfoVo.getRequestSoid(), registrationListCompleteInfoVo);
//                            latch.countDown();
                } catch (Exception e) {
                    log.info("RequestFormServiceImpl.queryAllRequestFormPageInfo 报告分页查询申请单接口封装返回体出错:{}", e.getMessage());
                }
            }
//                });
//            }
//            try {
//                latch.await(10, TimeUnit.SECONDS);
//            } catch (InterruptedException e) {
//                log.info("RequestFormServiceImpl.queryAllRequestFormPageInfo 报告分页查询申请单接口latch出错:{}", e.getMessage());
//            }
//            executorService.shutdownNow();
//            log.info("RequestFormServiceImpl.queryAllRequestFormPageInfo 报告分页查询申请单线程池关闭是否成功:{}", executorService.isTerminated());
        } catch (Exception e) {
            log.info("RequestFormServiceImpl.queryAllRequestFormPageInfo 报告分页查询申请单封装分页数据出错:{}", e.getMessage());
        } finally {
//            executorService.shutdownNow();
//            log.info("RequestFormServiceImpl.queryAllRequestFormPageInfo 报告分页查询申请单线程池关闭是否成功:{}", executorService.isTerminated());
        }
    }

    /**
     * 封装检查项信息
     *
     * @param serviceInstanceMap
     * @param requestPageInfo
     * @param examsInfoVo
     * @param businessNameMap        业务单元名map(执行单元)
     * @param dataSetSoidNameMap     编码体系soid对应中文名map
     * @param serviceInstanceNameMap 检查服务实例属性名map
     */
    @Override
    public void dealExamInfo(Map<BigDecimal, List<ServiceInstanceInfoDto>> serviceInstanceMap,
                             RequestPageInfoDto requestPageInfo,
                             ExamsInfoVo examsInfoVo,
                             Map<BigDecimal, String> businessNameMap,
                             Map<BigDecimal, String> dataSetSoidNameMap,
                             Map<BigDecimal, String> serviceInstanceNameMap) {
        HashSet<String> methodsSet = new HashSet<>();
        HashSet<String> partsSet = new HashSet<>();
        HashSet<String> examTypesSet = new HashSet<>();
        HashSet<String> checkUnitNamesSet = new HashSet<>();
        HashSet<String> instanceNameSet = new HashSet<>();
        List<String> instanceSoids = new ArrayList<>();
        //根据申请单标识在检查服务实例集合中获取改申请单下所有检查服务实例
        List<ServiceInstanceInfoDto> serviceInstanceInfos = serviceInstanceMap.get(new BigDecimal(requestPageInfo.getRequestSoid()));
        //将每个检查服务实例的状态设置成map用于前端处理下游业务时判断
        Map<String, String> serviceInstanceSoidMapStatus = serviceInstanceInfos.stream()
                .filter(ObjectUtil::isNotEmpty)
                .filter(a -> ObjectUtil.isNotEmpty(a.getMsdServiceInstanceSoid()))
                .filter(a -> ObjectUtil.isNotEmpty(a.getMsdInstanceServiceStatus()))
                .collect(Collectors.toMap(a -> a.getMsdServiceInstanceSoid().toPlainString(), b -> b.getMsdInstanceServiceStatus().toPlainString(), (a, b) -> a));
        examsInfoVo.setServiceInstanceSoidMapStatus(serviceInstanceSoidMapStatus);
        if (CollectionUtils.isEmpty(serviceInstanceInfos)) {
            return;
        }
        for (ServiceInstanceInfoDto serviceInstance : serviceInstanceInfos) {
            instanceSoids.add(serviceInstance.getMsdServiceInstanceSoid().toPlainString());
            //从主数据获取检查服务实例信息 todo 数据来源换成iris存储的检查服务实例信息
            StopWatch sw4 = new StopWatch();
            sw4.start("从主数据获取检查服务实例信息耗时");
            String check = ObjectUtils.isNotEmpty(serviceInstance.getExecuteDept()) && ObjectUtils.isNotEmpty(businessNameMap) ? businessNameMap.get(serviceInstance.getExecuteDept()) : null;
            String inst = ObjectUtils.isNotEmpty(serviceInstance.getMsdServiceInstanceSoid()) && ObjectUtils.isNotEmpty(serviceInstanceNameMap) ? serviceInstanceNameMap.get(serviceInstance.getMsdServiceInstanceSoid()) : null;
            checkUnitNamesSet.add(check);
            instanceNameSet.add(inst);
            sw4.stop();
            log.info("从主数据获取检查服务实例信息耗时:{}", sw4.prettyPrint());
            if (ObjectUtil.isNotEmpty(dataSetSoidNameMap)) {
                String part = ObjectUtils.isNotEmpty(serviceInstance.getExamParts()) ? dataSetSoidNameMap.get(serviceInstance.getExamParts()) : "";
                partsSet.add(part);
                String method = ObjectUtils.isNotEmpty(serviceInstance.getExamMethod()) ? dataSetSoidNameMap.get(serviceInstance.getExamMethod()) : "";
                methodsSet.add(method);
                String ctType = ObjectUtils.isNotEmpty(serviceInstance.getExamType()) ? dataSetSoidNameMap.get(serviceInstance.getExamType()) : "";
                examTypesSet.add(ctType);
            }

            String methods = apendNameStringFromSet(methodsSet);
            String parts = apendNameStringFromSet(partsSet);
            String examTypes = apendNameStringFromSet(examTypesSet);
            String instancesName = apendNameStringFromSet(instanceNameSet);
            String checkUnitNames = apendNameStringFromSet(checkUnitNamesSet);

            examsInfoVo.setExamServiceTypeName(examTypes);
            examsInfoVo.setMethods(methods);
            examsInfoVo.setParts(parts);
            examsInfoVo.setCheckUnitNames(checkUnitNames);
            examsInfoVo.setServiceInstanceNames(instancesName);
            examsInfoVo.setServiceInstanceSoids(instanceSoids);
        }
    }

    /**
     * 拼接字符串
     * @param nameStringSet
     * @return
     */
    @NotNull
    @Override
    public String apendNameStringFromSet(HashSet<String> nameStringSet) {
        String nameString = "";
        nameString = splitJointString(nameString, nameStringSet);
        nameString = cutOffLastChar(nameString);
        return nameString;
    }

    /**
     * 从set中获取字符串拼接
     * @param methods
     * @param methodsSet
     * @return
     */
    @Override
    public String splitJointString(String methods, HashSet<String> methodsSet) {
        for (String method : methodsSet) {
            methods += method + "+";
        }
        return methods;
    }

    /**
     * 去除尾部拼接字符
     * @param methodNames
     * @return
     */
    @Override
    public String cutOffLastChar(String methodNames) {
        if (methodNames.length() != 0) {
            methodNames = methodNames.substring(0, methodNames.length() - 1);
        }
        return methodNames;
    }

    /**
     * 字符串去重
     * @param part
     * @param set
     */
    @Override
    public void addStringToSet(String part, HashSet<String>... set) {
        if (StringUtils.isNotEmpty(part)) {
            for (int i = 0; i < set.length; i++) {
                set[i].add(part);
            }
        }
    }

    /**
     * 获取soid对应的中文含义
     * @param SoidMapNameVos
     * @param soid
     * @return
     */
    @Override
    @Deprecated
    public String setSoidMapName(List<SoidMapNameVo> SoidMapNameVos, BigDecimal soid) {
        String name = "";
        if (ObjectUtils.isNotEmpty(soid)) {
            name = masterDataSvc.getDataSetName(soid);
            SoidMapNameVos.add(SoidMapNameVo.builder()
                    .soid(soid.toPlainString())
                    .name(name)
                    .build());
        }
        return name;
    }
    /**
     * 批量获取检查服务实例信息并封装成map
     *
     * @param requestPageInfos
     * @return
     */
    @NotNull
    @Override
    public Map<BigDecimal, List<ServiceInstanceInfoDto>> changeServiceInstancesToMap(List<RequestPageInfoDto> requestPageInfos) {
        Map<BigDecimal, List<ServiceInstanceInfoDto>> serviceInstanceMap = new ConcurrentHashMap<>();
        //批量获取检查服务实例信息 todo 缓存
        List<BigDecimal> requestSoids = requestPageInfos.stream().map(RequestPageInfoDto::getRequestSoid).map(BigDecimal::new).collect(Collectors.toList());
        //根据申请单soid批量获取相应的检查服务实例
        RespBody<Map<BigDecimal, List<ServiceInstanceInfoDto>>> bigDecimalListMap = requestFormBmsSvc.getBigDecimalListMap(requestSoids);
        if (ObjectUtil.isNotEmpty(bigDecimalListMap) && ObjectUtil.isNotEmpty(bigDecimalListMap.getData())) {
            serviceInstanceMap = bigDecimalListMap.getData();
        }
        return serviceInstanceMap;
    }

    /**
     * 批量获取用户信息并封装成map
     *
     * @param requestPageInfos
     * @return
     */
    @NotNull
    @Override
    public Map<BigDecimal, PatientPageInfoVo> queryPatientInfoVosToMap(List<RequestPageInfoDto> requestPageInfos) {
        List<String> customerSoidsList = requestPageInfos.stream().filter(ObjectUtil::isNotEmpty).map(RequestPageInfoDto::getCustomerSoid).filter(ObjectUtil::isNotEmpty).distinct().collect(Collectors.toList());
        //根据personSoid批量获取个人信息
        PersonInfoConditionVo personInfoConditionVo = new PersonInfoConditionVo();
        personInfoConditionVo.setCustomerSoIds(customerSoidsList);
        RespBody<List<PatientInfoVo>> personInfos = personOperationApi.getPersonInfos(personInfoConditionVo);
        List<PatientInfoVo> personDetailInfos = ObjectUtils.isNotEmpty(personInfos) && ObjectUtils.isNotEmpty(personInfos.getData()) ? personInfos.getData() : new ArrayList<>();
        Map<BigDecimal, PatientPageInfoVo> personDetailInfosMap = new ConcurrentHashMap<>();
        for (PatientInfoVo personDetailInfo : personDetailInfos) {
            //填充身份证、地址等信息
            PatientPageInfoVo patientPageInfoVo = new PatientPageInfoVo();
            patientPageInfoVo.setAddress(personDetailInfo.getCustomerAddress());
            patientPageInfoVo.setAge(personDetailInfo.getAge());
            patientPageInfoVo.setApntPersonSoid(personDetailInfo.getPersonSoId());
            patientPageInfoVo.setBirthDate(DateUtil.format(personDetailInfo.getBirthDate(), DateFormatUtils.ISO_8601_EXTENDED_DATETIME_FORMAT.getPattern()));
            patientPageInfoVo.setGenderCode(personDetailInfo.getGenderCode());
            patientPageInfoVo.setGenderName(personDetailInfo.getGender());
            patientPageInfoVo.setPhoneNo(personDetailInfo.getContactNo());
            patientPageInfoVo.setIdCardNo(personDetailInfo.getIdCardNo());
            patientPageInfoVo.setIdCardType(personDetailInfo.getIdCardTypeCode());
            patientPageInfoVo.setPersonName(personDetailInfo.getPersonName());
//            personDetailInfosMap.put(new BigDecimal(personDetailInfo.getCustomerSoId()), patientPageInfoVo);
            personDetailInfosMap.put(new BigDecimal(personDetailInfo.getCustomerSoId().get(0)), patientPageInfoVo);
        }
        return personDetailInfosMap;
    }

}
